package com.xiaomaoguai.fcp.pre.kepler.redis.lock.service.impl;

import com.xiaomaoguai.fcp.pre.kepler.redis.utlis.CustomerExpressionParser;
import com.xiaomaoguai.fcp.pre.kepler.redis.lock.service.LockKeyBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @fileName: ELLockKeyBuilder.java
 * @author: WeiHui
 * @date: 2018/12/31 20:30
 * @version: v1.0.0
 * @since JDK 1.8
 */
public class SpringElLockKeyBuilder implements LockKeyBuilder {

	private ParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();

	private CustomerExpressionParser parser = new CustomerExpressionParser();

	@Override
	public String builder(String[] definitionKeys, Method method, Object[] parameterValues) {
		List<String> lockKeys = getSpelDefinitionKeyByEl(definitionKeys, method, parameterValues);
		return StringUtils.join(lockKeys, ":");
	}

	/**
	 * 通过el表达式获取锁key
	 *
	 * @param definitionKeys  锁key表达式
	 * @param parameterValues 方法入参
	 * @return 锁key
	 */
	private List<String> getSpelDefinitionKeyByEl(String[] definitionKeys, Method method, Object[] parameterValues) {
		List<String> definitionKeyList = new ArrayList<>();
		for (String definitionKey : definitionKeys) {
			if (definitionKey != null && !definitionKey.isEmpty()) {
				EvaluationContext context = new MethodBasedEvaluationContext(null, method, parameterValues, nameDiscoverer);
				Object value = parser.parseExpression(definitionKey).getValue(context);
				if (value != null) {
					definitionKeyList.add(value.toString());
				}
			}
		}
		return definitionKeyList;
	}

}
